/*********************************************
* vim: set sw=8 ts=8 si :
* Author: Guido Socher, Copyright: GPL
* This program is to test the led connected to
* PD5.
* Chip type           : ATMega8
* Clock frequency     : 12,000000 MHz
*********************************************/

#define __BUDOWA_PRODUKCYJNA 0






#define   F_CPU   12000000UL   /* czestotliwosc kwarcu */
#include <avr/io.h>

#define BIT(x) (1 << (x))
#define SETBITS(x,y) ((x) |= (y))
#define CLEARBITS(x,y) ((x) &= (~(y)))
#define SETBIT(x,y) SETBITS((x), (BIT((y))))
#define CLEARBIT(x,y) CLEARBITS((x), (BIT((y))))
#define BITSET(x,y) ((x) & (BIT(y)))
#define BITCLEAR(x,y) !BITSET((x), (y))
#define BITSSET(x,y) (((x) & (y)) == (y))
#define BITSCLEAR(x,y) (((x) & (y)) == 0)
#define BITVAL(x,y) (((x)>>(y)) & 1)

#include <inttypes.h>


#include <avr/delay.h>
#include <stdlib.h>
#include "lcd_lib.h"
#include <avr/pgmspace.h>
#include <avr\iom8.h>
//#include <float.h>
#include <avr\interrupt.h>
#define outp(a, b) b = a

#define USART_BAUD 18200ul //115200ul

#define USART_UBBR_VALUE ((F_CPU/(USART_BAUD<<4))-1)

#define cbi(port, bitnum) port &= ~(1 << bitnum)
#define sbi(port, bitnum) port |= (1 << bitnum) 

const uint8_t welcomeln1[] PROGMEM="BatTest v. 1.0.1\0";
//const uint8_t welcomeln2[] PROGMEM="lllllllllllllllllllllllllllllllllllllllllllllldla twstu avr alarm cell phone wersja rozwojowa alpha v 0.1\0";

//char buforwejascia[128];

volatile uint16_t licznik;
volatile uint8_t secadd;
volatile float poj_ws;   
volatile uint16_t poj_wh;
/*
volatile struct czas{
	uint8_t sec;
	uint8_t min;
	uint8_t hr;
	uint16_t day;
	uint8_t zmiana;
} time;
*/
volatile struct bat{
	uint16_t czastestu;
 //  uint64_t mws;
	double mwh;
  uint8_t opcje;
} bateria [3];

ISR(TIMER0_OVF_vect) {
TCNT0=0xff-125+1;
licznik++;
if (licznik>=375)
	{
		licznik = 0;
		secadd++;
	}
}

/*
void inittime()
{
time.sec=0;
time.min=0;
time.hr=0;
time.day=0;
time.zmiana=0;
}
/*
void addsec()
{
	if (secadd>1)
		{
			secadd--;
		}else return;
	time.zmiana=1;
	time.sec++;
	if (time.sec>59)
	{
		time.min++;
		time.sec=0;
		if (time.min > 59)
		{
			time.hr++;
			time.min=0;
			if(time.hr>23)
			{
				time.day++;
				time.hr=0;
			}
		}
	}
}

void printtime()
{
	char buffer[7];
//	if(time.zmiana)
//	{
//		time.zmiana=0;
//	} else return;
	
	LCDGotoXY(0,1);
	dtostrf()
	itoa( time.day, buffer, 10);   // convert interger into string (decimal format)
	LCDstring((uint8_t*)buffer,strlen(buffer));
	LCDstring((uint8_t*)"d ", 2);
	itoa( time.hr, buffer, 10);   // convert interger into string (decimal format)
	LCDstring((uint8_t*)buffer,strlen(buffer));
	LCDstring((uint8_t*)":", 1);
	itoa( time.min, buffer, 10);   // convert interger into string (decimal format)
	LCDstring((uint8_t*)buffer,strlen(buffer));
	LCDstring((uint8_t*)":", 1);
	itoa( time.sec, buffer, 10);   // convert interger into string (decimal format)
	LCDstring((uint8_t*)buffer,strlen(buffer));
	LCDstring((uint8_t*)"     ", 4);
 	
}
*/
#define nop() \
   asm volatile ("nop\n\twdr" )\

void InitADC()
{
 // Select Vref=AVcc
 ADMUX |= (1<<REFS0);
 //set prescaller to 128 and enable ADC 
 ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);    
}

uint16_t ReadADC(uint8_t ADCchannel)
{
 //select ADC channel with safety mask
 ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
 //single conversion mode
 ADCSRA |= (1<<ADSC);
 // wait until ADC conversion is complete
 while( ADCSRA & (1<<ADSC) );
 return ADC;
}
   
 void testbat(uint8_t kanal, uint8_t wyswietlany)
 {
	 double v=0,a=0;
	 if (bateria[kanal].opcje == 1)
	 {
		bateria[kanal].czastestu++;
	// bateria.mws =0;
		uint16_t mV, mA;
		mA = ReadADC(kanal*2);// + 480;		
		mV = ReadADC((kanal*2)+1);// + 24;
		v = ((double)mV * 5.0)/1024;
		a = ((double)mA * 5.0)/1024; 
		bateria[kanal].mwh += v*a*1000/(3600);
		if (v <= 3.0)
			{
				bateria[kanal].opcje = 0;
				
			}
			
			
	 }	
	 if (bateria[kanal].opcje == 0) cbi(PORTD,kanal+5); 
	//		   
	 if (kanal == wyswietlany)
	 {
		 LCDclr();
		 _delay_ms(2);
		 LCDGotoXY(0,0);
		 _delay_ms(1); 
		 char wynik[16]; 
		 dtostrf(v,4,2,wynik);// " 0.00-5.00" 
		LCDstring((uint8_t*)wynik,strlen(wynik));
		LCDstring((uint8_t*)"V ", 2);	 
		dtostrf(a,4,2,wynik);	 
		 LCDstring((uint8_t*)wynik,strlen(wynik));
		 LCDstring((uint8_t*)"A ", 2);
		 LCDGotoXY(0,1);
		 _delay_ms(1);
		 dtostrf(bateria[kanal].mwh,5,2,wynik);	 
		 LCDstring((uint8_t*)wynik,strlen(wynik));
		 LCDstring((uint8_t*)" ", 1);	 
		 _delay_ms(1);
		 utoa( bateria[kanal].czastestu, wynik, 10);
		 LCDstring((uint8_t*)wynik,strlen(wynik));
	 }
	 
	 
 }
 
 teststart(int kanal)
 {
	 bateria[kanal].opcje = 1;
	 bateria[kanal].czastestu = 0;
	 bateria[kanal].mwh = 0;
	 sbi(PORTD,kanal+5); 
	 #if __BUDOWA_PRODUKCYJNA
		_delay_ms(500); 
	 #endif
	  
 }	 
 
 void przyciski()
 {
	 if (!bit_is_set(PIND, PIND0))
	 {
		 teststart(0);
	 }		 
 }

int main(void)
{
int i; 	//  char buffer[10];//przykadowo 7
//int  num;
	secadd=0;
	poj_ws=0;
	i=0;
  // PORTC = 0;
  #if __BUDOWA_PRODUKCYJNA
	_delay_ms(500);
  #endif
    
   LCDinit();
   #if __BUDOWA_PRODUKCYJNA
    _delay_ms(500);
   #endif

   LCDclr();
   #if __BUDOWA_PRODUKCYJNA
    _delay_ms(500);
   #endif

   LCDvisible();
//   LCDcursorOnBlink();
#if __BUDOWA_PRODUKCYJNA
   _delay_ms(500);
#endif

   LCDhome();
   #if __BUDOWA_PRODUKCYJNA
	 _delay_ms(500);
   #endif

CopyStringtoLCD(welcomeln1, 0, 0);
#if __BUDOWA_PRODUKCYJNA
	 _delay_ms(5000);
#endif

//DDRC|= _BV(DDC0);
//USART_vInit();

	/*enable timer overflow interrupt*/

outp((1<<TOIE0), TIMSK);

/*set timer counter initial value*/

TCNT0=0;

/*start timer without presscaler*/

outp((1<<CS00), TCCR0);
TCCR0 = 1<<CS02; 

/* enable interrupts */

sei(); 
DDRD = _BV(2)|_BV(1)|_BV(0);

bateria[0].mwh = 0.0;
bateria[0].opcje= 0;
teststart(0);
 InitADC();
   while (1)
   {
	   przyciski();
      /* led on/off, pin=0 */
//	  	i++;
      //PORTC ^= _BV(PC0);
//	  	nop();
//		addsec();
//		printtime();
		if  (secadd > 0)
		{ 
      int i1=0;
      while (i1<3)
      {
			testbat(i1, 0);
      i1++;
      }
			secadd--;
		}
		

//		itoa( i, buffer, 10);   // convert interger into string (decimal format)
//		LCDGotoXY(0,1);
//	  LCDstring((uint8_t*)buffer,strlen(buffer));
      //_delay_ms(10);

   }
   return(0);
} 
